66. Прием у директора

 

Секретарь общеобразовательного учреждения Марта Георгиевна ежедневно начинала свой рабочий день с претензий к директору:

- Вот Вы, Иван Иванович, заместителю по учебной части программу для составления расписания уже приобрели. А что мне делать? Ведь мне нужно согласно Ваших требований составить график приема посетителей, а программу для планирования работы администрации Вы мне не приобрели...

Попробуйте помочь секретарю в ее роботе. Для этого вам нужно организовать прием посетителей на основании пожеланий, сделанных ими в соответствующей книге у секретаря.

Прием двух посетителей одновременно запрещен. В момент завершения приема одного посетителя может начаться прием другого – они встретились в дверях кабинета.

 

Вход. В первой строке находится количество посетителей n (n 1000), записавшихся на прием. В последующих n строках расположено по два числа T1i – время начала встречи с директором и через пробел T2i время ее завершения в формате hh:mm. Известно, что время задано в течении одних суток, все T2i T1i.

 

Выход. Выведите максимальное количество посетителей, которое сможет принять директор учреждения на протяжении рабочего дня.

 

Пример входа

Пример выхода

4

09:10 13:05

14:25 14:30

14:20 15:15

15:00 17:00

3

 

 

РЕШЕНИЕ

жадные алгоритмы

 

Анализ алгоритма

Создадим массив отрезков – временных интервалов [T1i; T2i). Отсортируем их по возрастанию времени окончания.

Далее жадным образом выбираем посетителей: перебираем интервалы слева направо и выбираем те, которые не пересекаются с уже выбранными.

 

Реализация алгоритма

Объявим класс отрезок, который будет хранить временной интервал [start; fin).

 

class segment

{

public:

  int start, fin;

  segment(int start, int fin) : start(start), fin(fin) {}

};

 

Набор входных интервалов храним в векторе v.

 

vector<segment> v;

 

Функция f сортировки интервалов. Интервалы сортируем по возрастанию времени их окончания.

 

int f(segment a, segment b)

{

  return a.fin <= b.fin;

}

 

Основная часть программы. Читаем входные данные.

 

scanf("%d", &n);

while (n--)

{

  scanf("%d:%d %d:%d", &h1, &m1, &h2, &m2);

 

Время в интервалах сохраняем в минутах.

 

  v.push_back(segment(h1 * 60 + m1, h2 * 60 + m2));

}

 

Сортируем отрезки времени.

 

sort(v.begin(), v.end(), f);

 

Принимаем посетителя, которому соответствует нулевой интервал (интервалы нумеруем с нуля). Пусть текущему посетителю, которого принимает директор, соответствует интервал времени cur. Поскольку директор всегда примет нулевого посетителя, установим cur = 0. В переменной res подсчитываем количество принятых посетителей. Поскольку директор принимает посетителя номер 0, то сначала установим res = 1.

 

cur = 0; res = 1;

 

Перебираем интервалы, начиная с i = 1.

 

for (i = 1; i < v.size(); i++)

{

 

Ищем интервал, начало которого не меньше времени окончания текущего. Принимаем посетителя из этого интервала и устанавливаем этот интервал текущим.

 

  if (v[i].start >= v[cur].fin)

  {

    cur = i;

    res++;

  }

}

 

Выводим количество принятых посетителей.

 

printf("%d\n", res);

 

Реализация алгоритма – вектор пар

Массив отрезков храним в векторе v.

 

vector<pair<int, int> > v;

 

Читаем входные данные. Время преобразуем в минуты. Время окончания ставим в паре первым, так как по умолчаннию вектор пар сортируется по первой компоненте.

 

scanf("%d", &n);

while (n--)

{

  scanf("%d:%d %d:%d", &h1, &m1, &h2, &m2);

  v.push_back(make_pair(h2 * 60 + m2, h1 * 60 + m1));

}

 

Сортируем пары.

 

sort(v.begin(), v.end());

 

В переменной res подсчитываем количество выбранных отрезков.

 

i = res = 0;

while (i < v.size())

{

 

В переменную temp заносим конец очередного выбранного отрезка.

 

  res++; temp = v[i++].first; // end

 

Ищем следующий отрезок, который начинается не раньше temp.

 

  while (i < v.size() && v[i].second < temp) i++;

}

 

Выводим количество принятых посетителей.

 

printf("%d\n", res);

 

Java реализация

 

import java.util.*;

 

class Segment

{

  int start, fin;

 

  public Segment(int start, int fin)

  {

    this.start = start;

    this.fin = fin;

  }

}

 

public class Main

{

  public static class MyFun implements Comparator<Segment>

  {

    public int compare(Segment a, Segment b)

    {

      return a.fin - b.fin;

    }

  }

  public static void main(String[] args)

  {

    Scanner con = new Scanner(System.in);

    int n = con.nextInt();

    ArrayList<Segment> seg = new ArrayList<Segment>();   

 

    for (int i = 0; i < n; i++)

    {

      String s = con.next();

      StringTokenizer st = new StringTokenizer(s, ":");

      int h = Integer.parseInt(st.nextToken());

      int m = Integer.parseInt(st.nextToken());

      int start = h * 60 + m;

 

      s = con.next();

      st = new StringTokenizer(s, ":");

      h = Integer.parseInt(st.nextToken());

      m = Integer.parseInt(st.nextToken());

      int fin = h * 60 + m;

      seg.add(new Segment(start,fin)); 

    }

     

    Collections.sort(seg, new MyFun());   

   

    int cur = 0, res = 1;

    for (int i = 1; i < seg.size(); i++)

    {

      if (seg.get(i).start >= seg.get(cur).fin)

      {

        cur = i;

        res++;

      }

    }

   

    System.out.println(res);

    con.close();

  }

}